package com.xyz.rok.tools.service.impl;

import com.xyz.rok.tools.mapper.MemberStatMapper;
import com.xyz.rok.tools.model.MemberStat;
import com.xyz.rok.tools.model.UnionMember;
import com.xyz.rok.tools.model.dto.StatDto;
import com.xyz.rok.tools.model.request.StatRequest;
import com.xyz.rok.tools.service.MemberStatService;
import com.xyz.rok.tools.service.UnionMemberService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

@Service
@Slf4j
public class MemberStatServiceImpl implements MemberStatService {

    @Resource
    private MemberStatMapper memberStatMapper;
    @Autowired
    private UnionMemberService unionMemberService;

    @Override
    public int deleteByPrimaryKey(Long id) {
        return memberStatMapper.deleteByPrimaryKey(id);
    }

    @Override
    public int insert(MemberStat record) {
        return memberStatMapper.insert(record);
    }

    @Override
    public int insertSelective(MemberStat record) {
        return memberStatMapper.insertSelective(record);
    }

    @Override
    public MemberStat selectByPrimaryKey(Long id) {
        return memberStatMapper.selectByPrimaryKey(id);
    }

    @Override
    public int updateByPrimaryKeySelective(MemberStat record) {
        return memberStatMapper.updateByPrimaryKeySelective(record);
    }

    @Override
    public int updateByPrimaryKey(MemberStat record) {
        return memberStatMapper.updateByPrimaryKey(record);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int insertOrUpdate(StatRequest memberStatRequest) {
        Integer day = Integer.parseInt(new SimpleDateFormat("yyyyMMdd").format(new Date()));
        if (memberStatRequest.getGameId() == null || memberStatRequest.getGameId() == 0) {
            return 0;
        }
        MemberStat memberStat = memberStatMapper.selectByGameIdAndDay(memberStatRequest.getGameId(), day);
        UnionMember unionMember = new UnionMember();
        unionMember.setServerId(memberStatRequest.getServerId());
        unionMember.setUnionId(memberStatRequest.getUnionId());
        unionMember.setGameId(memberStatRequest.getGameId());
        unionMember.setNickName(memberStatRequest.getNickName());
        unionMemberService.insertOrUpdate(unionMember);
        MemberStat insert = new MemberStat();
        if (memberStat == null) {
            BeanUtils.copyProperties(memberStatRequest, insert);
            insert.setCreateTime(new Date());
            insert.setDay(day);
            memberStatMapper.insertSelective(insert);
        } else {
            BeanUtils.copyProperties(memberStatRequest, insert);
            insert.setId(memberStat.getId());
            insert.setUpdateTime(new Date());
            memberStatMapper.updateByPrimaryKeySelective(insert);
        }
        return 1;
    }

    @Override
    public List<String> getFinishedNames(StatRequest memberStatRequest) {
        Integer day = Integer.parseInt(new SimpleDateFormat("yyyyMMdd").format(new Date()));
        return memberStatMapper.selectByServerIdUnionIdDay(memberStatRequest.getServerId(), memberStatRequest.getUnionId(), day);
    }

    @Override
    @Cacheable(value = "MemberStatRangeDate", key = "#unionId+':'+#beginDate+':'+#endDate")
    public List<StatDto> getMemberStatRangeDate(Long unionId, Integer beginDate, Integer endDate) {
        return memberStatMapper.selectMemberStatDto(unionId, beginDate, endDate);
    }

    @Override
    public List<StatDto> getMemberStatDate(Long unionId, Integer server, Integer day, String orderBy) {
        return memberStatMapper.selectMemberStatDtoByDay(unionId, server, day, orderBy);
    }

    @Override
    public List<Integer> getHasDataDay(Long unionId, Integer server) {
        return memberStatMapper.getHasDataDay(unionId, server);
    }

    @Override
    public List<StatDto> getMemberStatCompare(Long unionId, Integer server, Integer beginDate, Integer endDate, String orderBy) {
        List<StatDto> listBegin = memberStatMapper.selectMemberStatDtoByDay(unionId, server, beginDate, orderBy);
        List<StatDto> listEnd = memberStatMapper.selectMemberStatDtoByDay(unionId, server, endDate, orderBy);
        List<StatDto> listResult = new ArrayList<>();
        Set<Long> gameIdSet = new HashSet<>();
        Map<Long, StatDto> mapBegin = new HashMap((int) (listBegin.size() / 0.75 + 1));
        Map<Long, StatDto> mapEnd = new HashMap((int) (listEnd.size() / 0.75 + 1));
        for (StatDto memberStatDto : listBegin) {
            gameIdSet.add(memberStatDto.getGameId());
            mapBegin.put(memberStatDto.getGameId(), memberStatDto);
        }
        for (StatDto memberStatDto : listEnd) {
            gameIdSet.add(memberStatDto.getGameId());
            mapEnd.put(memberStatDto.getGameId(), memberStatDto);
        }
        StatDto memberStatDto = null;
        for (Long gameId : gameIdSet) {
            memberStatDto = new StatDto();
            memberStatDto.setGameId(gameId);
            if (mapBegin.get(gameId) == null || mapEnd.get(gameId) == null) {
                memberStatDto.setNickname(mapBegin.get(gameId) == null ? (mapEnd.get(gameId) == null ? "未知" : mapEnd.get(gameId).getNickname()) : mapBegin.get(gameId).getNickname());
                memberStatDto.setBeginValue(mapBegin.get(gameId) == null ? 0 : mapBegin.get(gameId).getValue());
                memberStatDto.setEndValue(mapEnd.get(gameId) == null ? 0 : mapEnd.get(gameId).getValue());
                memberStatDto.setValue(0);
            } else {
                memberStatDto.setNickname(mapEnd.get(gameId).getNickname());
                memberStatDto.setBeginValue(mapBegin.get(gameId).getValue());
                memberStatDto.setEndValue(mapEnd.get(gameId).getValue());
                memberStatDto.setValue(memberStatDto.getEndValue() - memberStatDto.getBeginValue());
            }
            listResult.add(memberStatDto);
        }
        Collections.sort(listResult, (o1, o2) -> {
            int v1 = o1.getValue();
            int v2 = o2.getValue();
            return v2 - v1;
        });
        return listResult;
    }

    @Override
    public List<StatDto> getMemberDKPCompare(Long unionId, Integer server, Integer beginDate, Integer endDate, Integer t4Kill, Integer t5Kill, Integer death) {
        List<StatDto> listBegin = memberStatMapper.selectMemberDKPByDay(unionId, server, beginDate, t4Kill, t5Kill, death);
        List<StatDto> listEnd = memberStatMapper.selectMemberDKPByDay(unionId, server, endDate, t4Kill, t5Kill, death);
        List<StatDto> listResult = new ArrayList<>();
        Set<Long> gameIdSet = new HashSet<>();
        Map<Long, StatDto> mapBegin = new HashMap((int) (listBegin.size() / 0.75 + 1));
        Map<Long, StatDto> mapEnd = new HashMap((int) (listEnd.size() / 0.75 + 1));
        for (StatDto memberStatDto : listBegin) {
            gameIdSet.add(memberStatDto.getGameId());
            mapBegin.put(memberStatDto.getGameId(), memberStatDto);
        }
        for (StatDto memberStatDto : listEnd) {
            gameIdSet.add(memberStatDto.getGameId());
            mapEnd.put(memberStatDto.getGameId(), memberStatDto);
        }

        StatDto memberStatDto = null;
        for (Long gameId : gameIdSet) {
            memberStatDto = new StatDto();
            memberStatDto.setGameId(gameId);
            if (mapBegin.get(gameId) == null || mapEnd.get(gameId) == null) {
                memberStatDto.setNickname(mapBegin.get(gameId) == null ? (mapEnd.get(gameId) == null ? "未知" : mapEnd.get(gameId).getNickname()) : mapBegin.get(gameId).getNickname());
                memberStatDto.setBeginValue(mapBegin.get(gameId) == null ? 0 : mapBegin.get(gameId).getValue());
                memberStatDto.setEndValue(mapEnd.get(gameId) == null ? 0 : mapEnd.get(gameId).getValue());
                memberStatDto.setValue(0);
            } else {
                memberStatDto.setNickname(mapEnd.get(gameId).getNickname());
                memberStatDto.setBeginValue(mapBegin.get(gameId).getValue());
                memberStatDto.setEndValue(mapEnd.get(gameId).getValue());
                memberStatDto.setValue(memberStatDto.getEndValue() - memberStatDto.getBeginValue());
            }
            listResult.add(memberStatDto);
        }
        Collections.sort(listResult, (o1, o2) -> {
            int v1 = o1.getValue();
            int v2 = o2.getValue();
            return v2 - v1;
        });
        return listResult;
    }

    @Override
    public List<StatDto> selectMemberStatDownloadByDay(Long unionId, Integer server, Integer day) {
        return memberStatMapper.selectMemberStatDownloadByDay(unionId, server, day);
    }
}
